#!/bin/bash
# Copyright 2019-2020 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================

set -e
BASEPATH=$(cd "$(dirname $0)"; pwd)
OUTPUT_PATH="${BASEPATH}/output"
export BUILD_PATH="${BASEPATH}/build"
# print usage message
usage()
{
  echo "Usage:"
  echo "sh build.sh [-j[n]] [-h] [-v] [-t] [-u] [-p] [-g]"
  echo ""
  echo "Options:"
  echo "    -h Print usage"
  echo "    -j[n] Set the number of threads used for building ACL, default is 8"
  echo "    -u Build and execute ut"
  echo "    -t Build ut with coverage tag"
  echo "    -p Build inference or train"
  echo "    -g product name"
  echo "    -v Display build command"
  echo "to be continued ..."
}

# check value of input is 'on' or 'off'
# usage: check_on_off arg_value arg_name
check_on_off()
{
  if [[ "X$1" != "Xon" && "X$1" != "Xoff" ]]; then
    echo "Invalid value $1 for option -$2"
    usage
    exit 1
  fi
}

# parse and set options
checkopts()
{
  VERBOSE=""
  THREAD_NUM=8
  PLATFORM="tiny_arm"
  ENABLE_C_UT="off"
  ENABLE_C_COV="off"
  PRODUCT="nano"
  # Process the options
  while getopts 'uthj:p:g:v' opt
  do
    OPTARG=$(echo ${OPTARG} | tr '[A-Z]' '[a-z]')
    case "${opt}" in
      u)
        ENABLE_C_UT="on"
        ;;
      t)
        ENABLE_C_COV="on"
        ;;
      h)
        usage
        exit 0
        ;;
      j)
        THREAD_NUM=$OPTARG
        ;;
      v)
        VERBOSE="VERBOSE=1"
        ;;
      p)
        PLATFORM=$OPTARG
        ;;
      g)
        PRODUCT=$OPTARG
        ;;
      *)
        echo "Undefined option: ${opt}"
        usage
        exit 1
    esac
  done
}

mk_dir() {
    local create_dir="$1"  # the target to make

    mkdir -pv "${create_dir}"
    echo "created ${create_dir}"
}

# create build path
build_acl_c()
{
  echo "create build directory and build ACL_C";
  mk_dir "${BUILD_PATH}"
  cd "${BUILD_PATH}"
  CMAKE_ARGS="-DBUILD_PATH=$BUILD_PATH"

  if [[ "X$ENABLE_C_COV" = "Xon" ]]; then
    CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_C_COV=ON"
  fi

  if [[ "X$ENABLE_C_UT" = "Xon" ]]; then
    CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_C_UT=ON"
  fi

  CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_OPEN_SRC=True -DCMAKE_INSTALL_PREFIX=${OUTPUT_PATH} -DPLATFORM=${PLATFORM} -DPRODUCT=${PRODUCT}"
  echo "${CMAKE_ARGS}"
  cmake ${CMAKE_ARGS} ..
  if [ 0 -ne $? ]
  then
    echo "execute command: cmake ${CMAKE_ARGS} .. failed."
    return 1
  fi

  if [[ "X$ENABLE_C_UT" = "Xon" || "X$ENABLE_C_COV" = "Xon" ]]; then
    make ascendcl_c_utest -j8
  else
    make ${VERBOSE} ascendcl_c -j${THREAD_NUM}
  fi
  if [ 0 -ne $? ]
  then
    echo "execute command: make ${VERBOSE} -j${THREAD_NUM} failed."
    return 1
  fi
  echo "ACL_C build success!"
}
generate_package()
{
  cd "${BASEPATH}"

  ACL_LIB_PATH="lib"
  ACL_EXTERNAL_PATH="inc/external/acl"
  
  rm -rf ${OUTPUT_PATH}
  
  mk_dir "${OUTPUT_PATH}/${ACL_LIB_PATH}"
  mk_dir "${OUTPUT_PATH}/${ACL_EXTERNAL_PATH}"

  find ${OUTPUT_PATH}/ -name acl_nano.tar -exec rm {} \;

  cd "${OUTPUT_PATH}"


  find ${BUILD_PATH}/c -maxdepth 1 -name "libascendcl.so" -exec cp -f {} ${OUTPUT_PATH}/${ACL_LIB_PATH} \;

  COMMON_INC=("acl_base.h" "acl.h" "acl_mdl.h" "acl_rt.h")
  for inc in "${COMMON_INC[@]}";
  do
    find ${BASEPATH}/${ACL_EXTERNAL_PATH} -maxdepth 1 -name "$inc" -exec cp -f {} ${OUTPUT_PATH}/${ACL_EXTERNAL_PATH} \;
  done

  tar -cf acl_nano.tar ${OUTPUT_PATH}
}

main()
{
  checkopts "$@"

  # Acl build start
  echo "---------------- ACL_C build start ----------------"
  g++ -v
  mk_dir ${OUTPUT_PATH}
  build_acl_c
  if [[ "$?" -ne 0 ]]; then
    echo "ACL_C build failed.";
    exit 1;
  fi
  echo "---------------- ACL_C build finished ----------------"

  rm -f ${OUTPUT_PATH}/libgmock*.so
  rm -f ${OUTPUT_PATH}/libgtest*.so
  rm -f ${OUTPUT_PATH}/lib*_stub.so

  chmod -R 750 ${OUTPUT_PATH}

  echo "---------------- ACL_C output generated ----------------"

  if [[ "X$ENABLE_C_UT" = "Xon" || "X$ENABLE_C_COV" = "Xon" ]]; then
    cp -rf ${BUILD_PATH}/tests/ut/acl/testcase_c/ascendcl_c_utest ${OUTPUT_PATH}

    RUN_TEST_CASE=${OUTPUT_PATH}/ascendcl_c_utest && ${RUN_TEST_CASE}
    if [[ "$?" -ne 0 ]]; then
      echo "!!! UT FAILED, PLEASE CHECK YOUR CHANGES !!!"
      echo -e "\033[31m${RUN_TEST_CASE}\033[0m"
      exit 1;
    fi
    echo "Generated coverage statistics, please wait..."
    cd ${BASEPATH}
    rm -rf ${BASEPATH}/cov
    mkdir ${BASEPATH}/cov
    lcov -c -d build/tests/ut/acl/testcase_c -o cov/tmp.info
    lcov -r cov/tmp.info '*/output/*' '*/build/opensrc/*' '*/build/proto/*' '*/third_party/*' '*/tests/*' '/usr/local/*' '/usr/include/*' -o cov/coverage.info
    cd ${BASEPATH}/cov
    genhtml coverage.info
  fi

  if [[ "X$ENABLE_C_UT" = "Xoff" ]]; then
    generate_package
    echo "---------------- ACL_C package archive generated ----------------"
  fi
}

main "$@"
